﻿using MediatR;
using Medical.Api.Write.Application.Command.DepartmentManagement.Recycling;
using Medical.Domain.DepartmentInfo;
using Medical.ErrorCode;
using Medical.Interstructrue.Base;
using Medical.Interstructrue;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Medical.Api.Write.Application.Handler.DepartmentManagement.Recycling
{
    /// <summary>
    /// 回收申请修改处理程序
    /// </summary>
    public class UpdateRecyclingCommandHandler : IRequestHandler<UpdateRecyclingCommands, ApiResult<int>>
    {
        private readonly ILogger<UpdateRecyclingCommandHandler> logger;
        private readonly IBaseRepository<RecyclingTable> recyclingRep;
        private readonly IBaseRepository<ItemTable> itemRep;
        private readonly MedicalDbContext dbContext;

        /// <summary>
        /// 构造函数，注入所需依赖
        /// </summary>
        /// <param name="logger">日志记录器</param>
        /// <param name="recyclingRep">回收申请仓储</param>
        /// <param name="itemRep">物品表仓储</param>
        /// <param name="dbContext">数据库上下文</param>
        public UpdateRecyclingCommandHandler(
            ILogger<UpdateRecyclingCommandHandler> logger, 
            IBaseRepository<RecyclingTable> recyclingRep, 
            IBaseRepository<ItemTable> itemRep,
            MedicalDbContext dbContext)
        {
            this.logger = logger;
            this.recyclingRep = recyclingRep;
            this.itemRep = itemRep;
            this.dbContext = dbContext;
        }

        /// <summary>
        /// 处理回收申请修改命令
        /// </summary>
        /// <param name="request">回收申请修改命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>API结果</returns>
        public async Task<ApiResult<int>> Handle(UpdateRecyclingCommands request, CancellationToken cancellationToken)
        {
            // 开启数据库事务
            using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken);
            try
            {
                // 验证回收申请数据
                if (request.recyclingTable == null)
                {
                    logger.LogWarning("回收申请数据为空");
                    return new ApiResult<int>()
                    {
                         Code = ApiEnums.Fail,
                         Data = 0,
                         Msg = "回收申请数据不能为空"
                    };
                }
                
                // 检查要修改的回收申请记录是否存在
                var existingRecycling = recyclingRep.GetModel(request.recyclingTable.Id);
                if (existingRecycling == null)
                {
                    logger.LogWarning("未找到ID为{Id}的回收申请记录", request.recyclingTable.Id);
                    return new ApiResult<int>()
                    {
                        Code = ApiEnums.NotFound,
                        Data = 0,
                        Msg = $"未找到ID为{request.recyclingTable.Id}的回收申请记录"
                    };
                }
                
                // 先分离实体，避免跟踪冲突
                dbContext.Entry(existingRecycling).State = EntityState.Detached;
                
                // 设置修改时间为当前时间
                request.recyclingTable.UpdateTime = DateTime.Now;
                
                // 更新回收申请
                recyclingRep.Update(request.recyclingTable);
                await dbContext.SaveChangesAsync(cancellationToken);
                
                // 如果有新的物品数据集合，则批量修改
                if (request.itemTables != null && request.itemTables.Any())
                {
                    // 不删除物品，只更新或添加
                    foreach (var item in request.itemTables)
                    {
                        item.RecyclingId = request.recyclingTable.Id;
                        item.UpdateTime = DateTime.Now;
                        
                        // 新增物品
                        if (item.Id == 0)
                        {
                            item.IsDeleted = false;
                            item.CreateTime = DateTime.Now;
                            await dbContext.AddAsync(item, cancellationToken);
                            logger.LogInformation("添加新物品，物品名称：{0}", item.ItemName);
                        }
                        // 更新现有物品
                        else
                        {
                            // 先查找再更新，避免跟踪冲突
                            var existingItem = await dbContext.Set<ItemTable>().FindAsync(item.Id);
                            if (existingItem != null)
                            {
                                // 更新属性值
                                dbContext.Entry(existingItem).CurrentValues.SetValues(item);
                                logger.LogInformation("更新现有物品，ID：{0}，物品名称：{1}", item.Id, item.ItemName);
                            }
                            else
                            {
                                // 如果找不到，当作新物品添加
                                item.IsDeleted = false;
                                item.CreateTime = DateTime.Now;
                                await dbContext.AddAsync(item, cancellationToken);
                                logger.LogInformation("物品ID存在但未找到，当作新物品添加：{0}", item.ItemName);
                            }
                        }
                    }
                    
                    await dbContext.SaveChangesAsync(cancellationToken);
                    logger.LogInformation("成功处理物品表数据，数量：{0}", request.itemTables.Count);
                }
                
                // 提交事务
                await transaction.CommitAsync(cancellationToken);
                
                logger.LogInformation("成功修改回收申请，ID：{0}", request.recyclingTable.Id);
                return new ApiResult<int>()
                {
                    Code = ApiEnums.Success,
                    Data = request.recyclingTable.Id,
                    Msg = "成功修改回收申请"
                };
            }
            catch (Exception ex)
            {
                // 回滚事务
                await transaction.RollbackAsync(cancellationToken);
                
                logger.LogError(ex, "修改回收申请时发生错误：{0}", ex.Message);
                return new ApiResult<int>()
                {
                    Code = ApiEnums.Fail,
                    Data = 0,
                    Msg = $"修改回收申请失败：{ex.Message}"
                };
            }
        }
    }
}

